package il.ac.tau.cg.ex3.math;

public class Vector 
{
	private double x;
	private double y;
	private double z;
	
	public Vector()
	{
		this(0.0, 0.0, 0.0);
	}
	
	public Vector(Point p1, Point p2)
	{
		this(p2.getX() - p1.getX(),
			 p2.getY() - p1.getY(),
			 p2.getZ() - p1.getZ());
	}
	
	public Vector(double x, double y, double z)
	{
		this.x = x;
		this.y = y;
		this.z = z;
	}
	
	@Override
	public Vector clone()
	{
		return new Vector(x, y, z);
	}
	
	public Vector normalize()
	{
		return scale(1.0 / length());
	}
	
	public double dot(Vector v)
	{
		return (x * v.x + y * v.y + z * v.z); 
	}
	
	public Vector cross(Vector v)
	{
		double a = y * v.z - z * v.y;
		double b = z * v.x - x * v.z;
		double c = x * v.y - y * v.x;
		
		return new Vector(a, b, c);
	}
	
	public boolean isOrtho(Vector vec)
	{
		return (dot(vec) == 0.0);
	}
	
	public double length()
	{
		return Math.sqrt(x * x + y * y + z * z);
	}
	
	public double getX() 
	{
		return x;
	}
	
	public void setX(double x) 
	{
		this.x = x;
	}
	
	public double getY() 
	{
		return y;
	}
	
	public void setY(double y) 
	{
		this.y = y;
	}
	
	public double getZ() 
	{
		return z;
	}
	
	public void setZ(double z) 
	{
		this.z = z;
	}
	
	public Vector scale(double s)
	{
		return new Vector(s * x, s * y, s * z);
	}
	
	public Vector add(Vector other)
	{
		return new Vector(x + other.x, y + other.y, z + other.z);
	}
	
	public Vector subtract(Vector other)
	{
		return add(other.negate());
	}
	
	public Vector negate()
	{
		return new Vector(-x, -y, -z);
	}
	
	public boolean isZero()
	{
		return ((x == 0.0) && (y == 0.0) && (z == 0.0));
	}
	
	public Vector arbitraryOrthogonal()
	{
		Vector v1 = new Vector(1.0, 0.0, 0.0);
		Vector v2 = new Vector(0.0, 1.0, 0.0);
		
		Vector r = cross(v1);
		
		if (r.isZero())
		{
			r = cross(v2);
		}
		
		return r;
	}
	
	@Override
	public boolean equals(Object o)
	{
		if ((o == null) || !(o instanceof Vector))
		{
			return false;
		}
		
		Vector v = (Vector)o;
		
		return (x == v.x) && (y == v.y) && (z == v.z);
	}
	
	@Override
	public int hashCode()
	{
		return new Double(x + y + z).hashCode();
	}
	
	@Override
	public String toString()
	{
		return "(" + x + ", " + y + ", " + z + ")";
	}
}
